import socket
import websocket
import json
import threading
import time
import logging
import uuid
import cv2


# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


class RobustDeviceWebSocketClient:
    def __init__(self, server_url, username="robust_device"):
        self.server_url = server_url
        self.username = username
        self.device_ip = self.get_device_ip()
        self.mac_address = self.get_mac_address()
        self.ws = None
        self.is_connected = False
        self.reconnect_interval = 5  # 重连间隔（秒）
        self.max_reconnect_attempts = 10
        self.reconnect_attempts = 0

    def get_device_ip(self):
        """获取设备IP地址"""
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.connect(("8.8.8.8", 80))
            ip = s.getsockname()[0]
            s.close()
            return ip
        except Exception as e:
            logger.error(f"获取IP地址失败: {e}")
            return socket.gethostbyname(socket.gethostname())

    def get_mac_address(self):
        """获取MAC地址"""
        try:
            mac = ':'.join(['{:02x}'.format((uuid.getnode() >> elements) & 0xff)
                            for elements in range(0, 2 * 6, 2)][::-1])
            return mac
        except Exception as e:
            logger.error(f"获取MAC地址失败: {e}")
            return "unknown"

    def build_websocket_url(self):
        """构建WebSocket连接URL"""
        url = f"{self.server_url}/webSocket/{self.username}?ip={self.device_ip}&mac={self.mac_address}"
        return url

    def on_message(self, ws, message):
        """接收消息回调"""
        logger.info(f"收到服务器消息: {message}")
        try:
            self.handle_server_message(message)
        except Exception as e:
            logger.error(f"处理消息异常: {e}")

    def on_error(self, ws, error):
        """错误处理回调"""
        logger.error(f"WebSocket错误: {error}")
        self.is_connected = False

    def on_close(self, ws, close_status_code, close_msg):
        """连接关闭回调"""
        logger.info(f"WebSocket连接已关闭 - 状态码: {close_status_code}, 消息: {close_msg}")
        self.is_connected = False
        self.attempt_reconnect()

    def on_open(self, ws):
        """连接建立回调"""
        logger.info(f"WebSocket连接成功 - 设备IP: {self.device_ip}, MAC: {self.mac_address}")
        self.is_connected = True
        self.reconnect_attempts = 0

        # 发送设备上线信息
        self.send_device_info()

    def handle_server_message(self, message):
        """处理服务器消息"""
        try:
            data = json.loads(message)
            # msg_type = data.get("type", "unknown")
            #
            # if msg_type == "ping":
            #     # 响应心跳
            #     self.send_pong()
            # elif msg_type == "command":
            #     # 处理命令
            #     self.execute_command(data.get("command"))
            # else:
            #     logger.info(f"未知消息类型: {msg_type}")

        except json.JSONDecodeError:
            logger.warning(f"无法解析JSON消息: {message}")

    def send_device_info(self):
        """发送设备信息"""
        device_info = {
            "type": "device_info",
            "ip": self.device_ip,
            "mac": self.mac_address,
            "status": "online",
            "timestamp": int(time.time())
        }
        self.send_message(json.dumps(device_info))

    def send_pong(self):
        """发送心跳响应"""
        pong_data = {
            "type": "pong",
            "timestamp": int(time.time())
        }
        self.send_message(json.dumps(pong_data))

    def execute_command(self, command):
        """执行服务器命令"""
        logger.info(f"执行命令: {command}")
        # 在这里实现具体的命令执行逻辑

        # 发送命令执行结果
        result = {
            "type": "command_result",
            "command": command,
            "result": "success",
            "timestamp": int(time.time())
        }
        self.send_message(json.dumps(result))

    def send_message(self, message):
        """发送消息"""
        if self.ws and self.is_connected:
            try:
                self.ws.send(message)
                logger.debug(f"发送消息: {message}")
            except Exception as e:
                logger.error(f"发送消息失败: {e}")
                self.is_connected = False
        else:
            logger.warning("WebSocket未连接，无法发送消息")

    def connect(self):
        """建立WebSocket连接"""
        ws_url = self.build_websocket_url()
        logger.info(f"连接到: {ws_url}")

        self.ws = websocket.WebSocketApp(
            ws_url,
            on_open=self.on_open,
            on_message=self.on_message,
            on_error=self.on_error,
            on_close=self.on_close
        )

        self.ws.run_forever()

    def attempt_reconnect(self):
        """尝试重连"""
        if self.reconnect_attempts < self.max_reconnect_attempts:
            self.reconnect_attempts += 1
            logger.info(f"尝试重连 ({self.reconnect_attempts}/{self.max_reconnect_attempts})...")
            time.sleep(self.reconnect_interval)

            # 在新线程中重连
            reconnect_thread = threading.Thread(target=self.connect)
            reconnect_thread.daemon = True
            reconnect_thread.start()
        else:
            logger.error("达到最大重连次数，停止重连")

    def start(self):
        """启动客户端"""
        try:
            connect_thread = threading.Thread(target=self.connect)
            connect_thread.daemon = True
            connect_thread.start()

            # 主线程保持运行
            while True:
                time.sleep(1)
                # 可以在这里添加其他业务逻辑

        except KeyboardInterrupt:
            logger.info("程序被用户中断")
            if self.ws:
                self.ws.close()




if __name__ == '__main__':
    server_url = "ws://192.168.3.42:3570/ruoyi-vue-service"
    client = RobustDeviceWebSocketClient(server_url, username="test")
    client.start()